Take control of your time

Filed under: Test automation, — Tags: Dependency injection, Test Driven Development — Thomas Sundberg — 2013-01-31

Testing is all about verifying that something works as expected. What are the challenges then? There are many, one very obvious is to actually know how it should work. Another challenge is to isolate the system under test so that it is possible to know what is tested and determine if that specific part works as expected.

Isolating the system under test means that you must have control over the environment that you perform the testing in. This is true for almost anything that is tested. I work with software systems so I am mostly interested in software testing. But the general idea here is applicable on any testing. If you don't have control over the surrounding systems then how can you actually test something in a deterministic way?

Time dependence

How would you do to test a behaviour that is dependent on the current time? Suppose that you should test that the shipping cost in an online store is calculated correctly. There is a business rule that says that shipping should be free a month before Christmas and that it should cost 17 the rest of the year. This means that the cost will depend on the date an order is placed.

An implementation of this rule could be something like this:

public int calculateShipping() {
    int aMonth = 31;

    Calendar today = GregorianCalendar.getInstance();
    int year = today.get(Calendar.YEAR);

    Calendar christmas = GregorianCalendar.getInstance();
    christmas.set(year, Calendar.DECEMBER, 24);

    int christmasDay = christmas.get(Calendar.DAY_OF_YEAR);
    int currentDay = today.get(Calendar.DAY_OF_YEAR);
    int daysBeforeChristmas = christmasDay - currentDay;

    if (daysBeforeChristmas < aMonth && daysBeforeChristmas > -1) {
        return 0;
    } else {
        return 17;
    }
}

This method has at least two problems. A minor issue is that the day Christmas is celebrated is different in different countries. Some celebrate it 24 of December, others 25 of December.

The largest problem is not which date Christmas is celebrated though, but the fact that it is only possible to verify the behaviour during a few days of the year.

Suppose that this method is implemented in mid December, tested with a few unit tests and executed in a continuous integration server. Everything would be nice and green. The build will, however, start breaking after Christmas and break every time it is executed. The test will probably be disabled and probably forgotten. The result may be that we build up a set of disabled tests and all of a sudden it may be ok to have ignored tests.

Take control

How can this method be refactored so it gets testable? It will become testable if you take control over the context where the test will be executed. Supply the method with a date you have control over. This means that you can create tests for all interesting dates surrounding the edges for free shipping. One day before the shipping should be free, the first day that should be free, the last free day, the first day after and so on. You can very easy create all cases that will box in the shipping rule and always be sure that you will know when somebody breaks the functionality.

An implementation may look like this:

public int calculateShipping(Calendar today) {
    int aMonth = 31;

    int year = today.get(Calendar.YEAR);

    Calendar christmas = GregorianCalendar.getInstance();
    christmas.set(year, Calendar.DECEMBER, 24);

    int christmasDay = christmas.get(Calendar.DAY_OF_YEAR);
    int currentDay = today.get(Calendar.DAY_OF_YEAR);
    int daysBeforeChristmas = christmasDay - currentDay;

    if (daysBeforeChristmas < aMonth && daysBeforeChristmas > -1) {
        return 0;
    } else {
        return 17;
    }
}

The only difference is that you now take control of the time. You can set the parameter today to whatever you want in a test. You don't depend on the system date where this code is executed.

This pattern of taking control can be extended to almost anything that surrounds a piece of software. If you don't have control, then you really can't execute your tests and expect a deterministic behaviour. This goes for any surrounding system, a main frame, a database with a production copy and so on.

Conclusion

If you are not in control, you will always be depending on other systems to behave deterministic. Surrounding systems in a development environment seldom behave deterministic all times. This may be one of the largest problems that you must solve when you implement test automation.

Acknowledgements

This post has been reviewed by some people who I wish to thank for their help

Thank you very much for your feedback!

Resources



(less...)

Pages

About
Events
Why

Categories

Agile
Automation
BDD
Clean code
Continuous delivery
Continuous deployment
Continuous integration
Cucumber
Culture
Design
Executable specification
Gradle
Guice
J2EE
JUnit
Java
Linux
Load testing
Maven
Mockito
Pair programming
PicoContainer
Programming
Public speaking
Quality
Recruiting
Requirements
Scala
Selenium
Software craftsmanship
Software development
Spring
TDD
Teaching
Technical debt
Test automation
Tools
Web
Windows
eXtreme Programming

Authors

Thomas Sundberg
Adrian Bolboaca

Archives

Meta

rss RSS