Add this to yml file:
- name: Install dependencies
run: |
# ...
sudo apt-get install -y xvfb
Add this before root = tk.Tk()
:
if os.name != "nt" and os.getenv("GITHUB_ACTIONS"):
os.system('Xvfb :1 -screen 0 1600x1200x16 &')
os.environ["DISPLAY"] = ":1.0"
Patch the mainloop
functions of tkinter
and the tkinter
widgets you use. If you use winfo_*
functions patch those too. Example:
"""
TkConsole Test Patches
This module provides fake classes to patch certain Tkinter classes for testing purposes.
These fake classes allow for mocking the behavior of Tkinter's classes during unit tests.
Classes:
FakeTk (class): A fake Tkinter root window class for testing.
FakeScrolledText (class): A fake ScrolledText class for testing.
Usage:
These fake classes are used in unit tests to mock the behavior of Tkinter classes and methods,
ensuring that the unit tests are isolated and independent of the actual Tkinter functionality.
"""
import tkinter as tk
from tkinter import scrolledtext
class FakeTk(tk.Tk):
"""
FakeTk class
This class provides a fake implementation of the Tkinter root window class for testing purposes.
Methods:
mainloop(self, **kwargs): Mocks the mainloop method of Tkinter's root window.
"""
def __init__(self):
"""
Initialize a fake Tkinter root window for testing purposes.
Returns:
None
"""
super(FakeTk, self).__init__()
def mainloop(self, **kwargs):
"""
Mocks the mainloop method of Tkinter's root window.
Args:
**kwargs: Additional keyword arguments (ignored).
Returns:
None
"""
pass
class Entry(tk.Entry):
"""
Fake Entry class
This class provides a fake implementation of the Entry widget for testing purposes.
Methods:
mainloop(self, n: int = ...) -> None: Mocks the mainloop method of Tkinter's Entry widget.
"""
def __init__(self):
"""
Initialize a fake Entry widget for testing purposes.
Returns:
None
"""
super(FakeTk.Entry, self).__init__()
def mainloop(self, n: int = ...) -> None:
"""
Mocks the mainloop method of Tkinter's Entry widget.
Args:
n (int): Number of iterations (ignored).
Returns:
None
"""
pass
class FakeScrolledText(scrolledtext.ScrolledText):
"""
FakeScrolledText class
This class provides a fake implementation of the ScrolledText class for testing purposes.
Methods:
mainloop(self, n: int = ...) -> None: Mocks the mainloop method of Tkinter's ScrolledText.
winfo_height(self) -> int: Mocks the winfo_height method of Tkinter's ScrolledText.
"""
def __init__(self, master=None, **kw):
"""
Initialize a fake ScrolledText widget for testing purposes.
Args:
master: The master widget (ignored).
**kw: Additional keyword arguments (ignored).
Returns:
None
"""
super(FakeScrolledText, self).__init__()
def mainloop(self, n: int = ...) -> None:
"""
Mocks the mainloop method of Tkinter's ScrolledText.
Args:
n (int): Number of iterations (ignored).
Returns:
None
"""
pass
def winfo_height(self) -> int:
"""
Mocks the winfo_height method of Tkinter's ScrolledText.
Returns:
int: Height of the ScrolledText.
"""
return 500
Use the patched functions as in the following example:
def setUp(self):
"""
Set up the test environment.
This method creates a Tkinter root window and initializes a Console instance for testing.
It also initializes attributes for accessing the text area, entry widget, and user_input_var.
Returns:
None
"""
if os.name != "nt" and os.getenv("GITHUB_ACTIONS"):
os.system('Xvfb :1 -screen 0 1600x1200x16 &')
os.environ["DISPLAY"] = ":1.0"
self.root = FakeTk()
self.console = Console(self.root)
self.console.text_area = FakeScrolledText(
self.console.parent, wrap=tk.WORD, font=self.console.font, background=self.console.background,
foreground=self.console.foreground, padx=0,
pady=0, borderwidth=0, border=0.0, insertborderwidth=0, selectborderwidth=0
)
self.text_area = self.console.text_area
self.entry = self.console.entry
self.user_input_var = self.console.user_input_var
And use threading
and queue
modules for threading. If you don't do this all tkinter
windows open in same time and causes error.