Neither of these implementations has any real benefit.
In test2.py, datetime = datetime
is essentially a no-op. It does not change the state of the module. This is completely useless.
test1.py doesn't actually behave particularly differently, either. It just sets datetime
as a class attribute, which means that it looks to the class to find datetime
instead of the module. This might perform better in some very heavy load circumstances, but not enough that you should be worried about it unless you already know what you're doing.
The fact they invoke self.datetime.time()
, though, suggests to me that the author's (assuming you saw someone doing this in their own code) intention was that datetime
could be temporarily replaced at runtime, like this:
class FakeDatetime:
def time(self):
return 'from fake datetime'
t = Test1()
t.datetime = FakeDatetime()
print(t.getnow()) # Prints "from fake datetime"
To me, this looks like a misguided attempt to enable using a mock or stub for automated tests. They probably intend for it to be used something like this:
import unittest
from test1 import Test1
class TestStringMethods(unittest.TestCase):
def test_my_method():
mock = MyMock()
expected_value = 'my value'
# Set up code to make mock.time() return expected value
t = Test1()
t.datetime = mock
assert t.time() == expected_value
The standard solution to mocking in Python is the unittest.mock
module (or the mock
package if using Python 3.2 or older). This module encourages patching to replace dependencies, rather than something manual like the code you presented:
test3.py
import datetime
class Test3:
def getnow(self):
return datetime.time()
test3tests.py
import unittest
from unittest import mock
from test3 import Test3
class TestStringMethods(unittest.TestCase):
@mock.patch('test3.datetime')
def test_my_method(datetime_mock):
expected_value = 'my value'
datetime_mock.time.return_value = expected_value
t = Test3()
assert t.time() == expected_value
# Original datetime is restored by patch automatically when method exits