Reputation: 1541
I decided to use TDD approach in my project. As a start, I focused on a small part of a use case:
Validate AccessCode.
An AccessCode, a date in Julian format, is valid if it is less than or equal to today.
Step 1: Write a test
def test_should_validate_accessdate(self):
assert application.is_accessdate_valid(56746)
Step 2: Run to fail
Done.
Step 3: Make the test pass
In application.py,
def is_accessdate_valid(accessdate):
return True
Step 4: Run to pass
Done.
Step 5: Refactor
There is nothing to refactor. But, the hard-coded return value sucks.
Now, repeat:
Step 1: Write a new test
def test_should_invalidate_accessdate(self):
assert not application.is_accessdate_valid(54990)
Step 2: Run to fail
Done.
Step 3: Make the test pass
In this case, the hard-coded return value is a pain. So, I need to remove it, instead generalizing some logic for the tests to pass.
def is_accessdate_valid(accessdate):
today_julian = julian_to_julian5(calendar_to_julian(datetime.utcnow()))
return accessdate >= today_julian
I am not still sure if I did the right thing by taking such a huge leap in one step. But, I saw no other way to make the test pass without failing the other test. Suggestions are welcome here.
Step 4: Run to pass the test
Done.
Step 5: Run to pass all the tests
Done.
Initially, I was proud that I was able to define a function by writing a test for it first, and then shaping it up through more test(s).
However, later I realized that the test that checks for valid accessdate will start failing once today's date crosses the input accessdoday's date.
One thing I could do is to provide a dynamically calculated input accessdate:
1. Add a day or two to today's date.
2. Convert the above resulting date to julian format.
3. Use the above Julian result as input accessdate.
However, something doesn't feel right there.
Am I going on the right path here? Or did I go astray in between somewhere? Or the function design wrong in the first place, assuming that I should have chosen a different signature instead?
Any suggestions or thrashing are welcome.
Upvotes: 2
Views: 115
Reputation: 2161
You don't want to write unit tests that are time-dependent. So write tests that are relative to a date that is an argument - thus stays constant - or use the mocking approach mentioned by jonrsharpe. This leaves you only the problem of determining whether your mechanism for determining the time-dependent component works, but not whether the logic works.
This applies to other environmental things as well - machine names, directory pathnames, historical stock prices, etc.
Upvotes: 2