Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
__pycache__
*.pyc
Empty file added dft/__init__.py
Empty file.
52 changes: 52 additions & 0 deletions dft/constructor_injection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/python
# -*- coding : utf-8 -*-
import datetime

"""
Port of the Java example of "Constructor Injection" in
"xUnit Test Patterns - Refactoring Test Code" by Gerard Meszaros
(ISBN-10: 0131495054, ISBN-13: 978-0131495050) accessible in outdated version on
http://xunitpatterns.com/Dependency%20Injection.html.

production code which is untestable:

class TimeDisplay(object):

def __init__(self):
self.time_provider = datetime.datetime

def get_current_time_as_html_fragment(self):
current_time = self.time_provider.now()
current_time_as_html_fragment = "<span class=\"tinyBoldText\">" + current_time.hour + ":" + current_time.minute + "</span>"
return current_time_as_html_fragment
"""

class TimeDisplay(object):

def __init__(self, time_provider):
self.time_provider = time_provider

def get_current_time_as_html_fragment(self):
current_time = self.time_provider.now()
current_time_as_html_fragment = "<span class=\"tinyBoldText\">" + current_time + "</span>"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's better to use .format here instead of + (true for all string concatenations that you do)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DONE

Copy link
Owner

@faif faif Apr 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks but that's not what I meant. The idea is to avoid string concatenations completely since a) strings are immutable and there is some overhead included, b) it is more idiomatic in Python to use .format. The idea looks like that: "<span class=\"tinyBoldText\">{}{}</span>".format(current_time.hour, current_time.minute)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that exactly what I changed in commit 4cca032?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, sorry, I missed that :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is already late 😉

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for reviewing

return current_time_as_html_fragment

class ProductionCodeTimeProvider(object):
"""
Production code version of the time provider (just a wrapper for formatting
datetime for this example).
"""

def now(self):
current_time = datetime.datetime.now()
current_time_formatted = str(current_time.hour) + ":" + str(current_time.minute)
return current_time_formatted

class MidnightTimeProvider(object):
"""
Class implemented as hard-coded stub (in contrast to configurable stub).
"""

def now(self):
current_time_is_always_midnight = "24:01"
return current_time_is_always_midnight
47 changes: 47 additions & 0 deletions tests/test_constructor_injection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import unittest

from dft.constructor_injection import TimeDisplay, MidnightTimeProvider, ProductionCodeTimeProvider, datetime

"""
Port of the Java example of "Constructor Injection" in
"xUnit Test Patterns - Refactoring Test Code" by Gerard Meszaros
(ISBN-10: 0131495054, ISBN-13: 978-0131495050) accessible in outdated version on
http://xunitpatterns.com/Dependency%20Injection.html.

Test code which will almost always fail (if not exactly 12:01) when untestable
production code (have a look into constructor_injection.py) is used:

def test_display_current_time_at_midnight(self):
class_under_test = TimeDisplay()
expected_time = "24:01"
result = class_under_test.get_current_time_as_as_html_fragment()
self.assertEqual(result, expected_time)
"""

class ConstructorInjectionTest(unittest.TestCase):

def test_display_current_time_at_midnight(self):
"""
Would almost always fail (despite of right at/after midnight) if
untestable production code would have been used.
"""
time_provider_stub = MidnightTimeProvider()
class_under_test = TimeDisplay(time_provider_stub)
expected_time = "<span class=\"tinyBoldText\">24:01</span>"
self.assertEqual(class_under_test.get_current_time_as_html_fragment(), expected_time)

def test_display_current_time_at_current_time(self):
"""
Just as justification for working example with the time provider used in
production. (Will always pass.)
"""
production_code_time_provider = ProductionCodeTimeProvider()
class_under_test = TimeDisplay(production_code_time_provider)
current_time = datetime.datetime.now()
expected_time = "<span class=\"tinyBoldText\">{}:{}</span>".format(current_time.hour, current_time.minute)
self.assertEqual(class_under_test.get_current_time_as_html_fragment(), expected_time)

if __name__ == "__main__":
unittest.main()