From d1c4efe47bd7ee2d403afea6b392660cb82815cc Mon Sep 17 00:00:00 2001 From: Florian Kromer Date: Tue, 25 Apr 2017 20:21:14 +0200 Subject: [PATCH] add: constructor injection files on clean branch --- dft/constructor_injection.py | 51 +++++++++++++++++++++++++++++ tests/test_constructor_injection.py | 42 ++++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 dft/constructor_injection.py create mode 100644 tests/test_constructor_injection.py diff --git a/dft/constructor_injection.py b/dft/constructor_injection.py new file mode 100644 index 000000000..79596b05f --- /dev/null +++ b/dft/constructor_injection.py @@ -0,0 +1,51 @@ +#!/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) + +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 = "{}".format(current_time) + 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 = "{}".format(current_time) + 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 = "{}:{}".format(current_time.hour, 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 diff --git a/tests/test_constructor_injection.py b/tests/test_constructor_injection.py new file mode 100644 index 000000000..5ae9ccff2 --- /dev/null +++ b/tests/test_constructor_injection.py @@ -0,0 +1,42 @@ +#!/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) + +Test code which will almost always fail (if not exactly 12:01) when untestable +production code (production code time provider is datetime) 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): + """ + Will almost always fail (despite of right at/after midnight). + """ + time_provider_stub = MidnightTimeProvider() + class_under_test = TimeDisplay(time_provider_stub) + expected_time = "24:01" + 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. (Will always pass.) + """ + production_code_time_provider = ProductionCodeTimeProvider() + class_under_test = TimeDisplay(production_code_time_provider) + current_time = datetime.datetime.now() + expected_time = "{}:{}".format(current_time.hour, current_time.minute) + self.assertEqual(class_under_test.get_current_time_as_html_fragment(), expected_time) +