Skip to main content
1 of 6
Pablo
  • 95
  • 1
  • 10

How to test implementation of ports-and-adaptors for tkinter

I'm trying to test my implementation of ports-and-adaptors for tkinter.

Assume I have a tkinter Entry declared like so:

entry = tk.Entry(container)
entry.value = tk.StringVar()
entry.configure(textvariable=entry.value)

In module ports.py I have a simple function to set the value:

def set_widget_value(widget, value):
    widget.value.set(value)

In module adaptors.py I have a class that provides domain specific method to set the value:

from myapp.gui.ports import set_widget_value


class EntryAdaptor(object):
    """Wraps a Tkinter Entry widget."""

    def __init__(self, entry):
        self._entry = entry

    def set_value(self, value):
        set_widget_value(self._entry, value)

To test my adaptor layer I have come up with two options.

Option A

import unittest
import unittest.mock as mock

from myapp.gui.adaptors import EntryAdaptor


class EntryAdaptorTests(unittest.TestCase):

    def test_should_set_value_of_entry(self):
        entry = mock.Mock()  
        adaptor = EntryAdaptor(entry)

        text = 'some user-typed text'
        adaptor.set_value(text)
        entry.value.set.\
            assert_called_once_with(text)

Option B

import unittest
import unittest.mock as mock


class TestSomething(unittest.TestCase):    

    def test_should_set_value_of_entry(self):
        entry = mock.Mock()
        with mock.patch('myapp.gui.ports.set_widget_value') as set_widget_value:
            from myapp.gui.adaptors import EntryAdaptor
            adaptor = EntryAdaptor(entry)

            text = 'some user-typed text'
            adaptor.set_value(text)

            set_widget_value.assert_called_once_with(entry, text)

In Option A, I'm looking at the mocked tkinter.Entry object and checking if it was called as expected; this has the disadvantage of mocking the external tkinter API.

In Option B, I mock my set_widget_value() function and check if it was called as expected; this has the disadvantage of performing the import of EntryAdaptor within the test_should_set_value_of_entry() method because of the dependency of adaptors.py to ports.py.

Which is the best way to perform the test: A, B or something completely different?

Pablo
  • 95
  • 1
  • 10