views:

221

answers:

5

I've got a simple function like this:

    function CreateFileLink()
    {
            global $Username;

            return date("d-m-y-g-i");
    }

How do you write code to test a function like that where the return data is variable?

A: 

Well, if you use a unit test, you know which day, month and year you are testing the function.

So, call the function. You have the current time (when the test is run). Subtract the current time from the function time. The difference should be very small (like 2 seconds).

If the difference is greater than that, I would fail the test. (depending on the speed of your system of course).

cbrulak
A: 

It looks like the only test you can run on this function is that it does not throw an exception. There is no need to test the return data, as it's generated by an external entity (the date() function).

Randolpho
+2  A: 

What your unit tests need to do is setup the environment for this function to work properly, in other words, you simulate as if the system was running by setting up other variables, then you SHOULD be able to know what it will return based on how your unit test set up these variables (unless of course the return value is a random number, in which case all you could do, as Randolpho suggested, is make sure it doesn't throw).

If your unit tests is found in this situation of setting up and calling a whole bunch of other methods just to test this function, it's probably a good indication that your function is tightly coupled and you could probably break it down into smaller pieces.

Ricardo Villamil
+3  A: 

You could test it if you could somehow get control over that date() function. For example, in this case, you only care that the date function is being called with "d-m-y-g-i"; you don't really care about the output of it. Maybe something like:

function CreateFileLink(DateProvider dateProvider)
{
        global $Username;

        return dateProvider.date("d-m-y-g-i");
}

Sorry, I don't even know what language this is but hopefully you can see my point. In production code, you'd call this by doing:

DateProvider standardDateProvider = new DateProvider() { Date date(String str) { return date(str); } };
CreateFileLink(standardDateProvider);

But in your test, you can provide an alternate implementation that will throw an error if the input isn't what you expect:

DateProvider mockProvider = new DateProvider() 
{
    Date date(String str) 
    {
        if(str != "d-m-y-g-i") throw Exception();
        return "success";
    }
}
Outlaw Programmer
+2  A: 

There's a Google Tech Talk good about dependency injection.

Basically, the ideal way to create testable code is to make all of your dependencies explicit so that you do not wind-up with situations where calling the same function twice can result in two different answers.

In the case of dates and such, if you create an "system object" which you pass explicitly into your function, you could then create a "test system object" which could used for testing and which would return fixed values rather than returning the current date.

Joe Soul-bringer
Are you really suggesting that the OP should create a mock of the system date function?
benjismith
What I'd suggest is exactly what "Outlaw programmer" describes in his answer.
Joe Soul-bringer